"""
Video processing for PowerPoint presentations.
"""

import os
from pathlib import Path
from typing import Tuple, Optional

from PIL import Image
from pptx.slide import Slide
from pptx.util import Inches

from ..styling.theme_manager import ThemeManager
from .thumbnail_generator import ThumbnailGenerator


class VideoProcessor:
    """Handles video processing and insertion into slides."""
    
    def __init__(self, theme_manager: ThemeManager):
        self.theme_manager = theme_manager
        self.thumbnail_generator = ThumbnailGenerator()
    
    def add_video_to_slide(self, slide: Slide, video_path: str, y_position: float, 
                          poster_frame_path: Optional[str] = None, 
                          alt_text: Optional[str] = None) -> float:
        """
        Add a video to a slide at the specified Y position.
        Returns the height of the added video.
        """
        # Resolve video path
        resolved_video_path = self._resolve_media_path(video_path)
        if not resolved_video_path or not resolved_video_path.exists():
            raise FileNotFoundError(f"Video not found: {video_path}")
        
        # Resolve poster frame path
        resolved_poster_path = None
        if poster_frame_path:
            resolved_poster_path = self._resolve_media_path(poster_frame_path)
            if not resolved_poster_path or not resolved_poster_path.exists():
                # If custom poster frame not found, extract from video
                resolved_poster_path = self._extract_video_thumbnail(resolved_video_path, alt_text)
        else:
            # Try to find an existing poster frame first
            resolved_poster_path = self._find_auto_poster_frame(resolved_video_path)
            
            # If no existing poster frame, extract from video
            if not resolved_poster_path:
                resolved_poster_path = self._extract_video_thumbnail(resolved_video_path, alt_text)
        
        # Get video constraints
        constraints = self.theme_manager.get_image_constraints()
        layout = self.theme_manager.get_layout_dimensions()
        
        # Calculate video dimensions based on actual video resolution
        video_width, video_height = self._calculate_video_size(
            constraints['max_width'], 
            constraints['max_height'],
            resolved_video_path
        )
        
        # Center the video horizontally
        x_position = layout['content_left'] + (layout['content_width'] - video_width) / 2
        
        # Determine MIME type
        mime_type = self._get_video_mime_type(resolved_video_path)
        
        # Add video to slide
        try:
            if resolved_poster_path:
                slide.shapes.add_movie(
                    str(resolved_video_path),
                    x_position,
                    y_position,
                    video_width,
                    video_height,
                    poster_frame_image=str(resolved_poster_path),
                    mime_type=mime_type
                )
            else:
                # If no poster frame, create a placeholder
                placeholder_path = self._create_video_placeholder(alt_text or "Video")
                slide.shapes.add_movie(
                    str(resolved_video_path),
                    x_position,
                    y_position,
                    video_width,
                    video_height,
                    poster_frame_image=str(placeholder_path),
                    mime_type=mime_type
                )
        except Exception as e:
            # If video insertion fails, add error text
            from pptx.util import Inches
            text_shape = slide.shapes.add_textbox(
                x_position,
                y_position,
                video_width,
                Inches(0.5)
            )
            text_shape.text = f"[Video not supported: {video_path}]"
            return Inches(0.7)
        
        return video_height
    
    def _resolve_media_path(self, media_path: str) -> Optional[Path]:
        """Resolve media path, handling relative paths."""
        path = Path(media_path)
        
        # If absolute path exists, use it
        if path.is_absolute() and path.exists():
            return path
        
        # Try relative to current working directory
        cwd_path = Path.cwd() / path
        if cwd_path.exists():
            return cwd_path
        
        # Try relative to common media directories
        common_dirs = ['videos', 'media', 'assets', 'movies']
        for dir_name in common_dirs:
            dir_path = Path.cwd() / dir_name / path.name
            if dir_path.exists():
                return dir_path
        
        return None
    
    def _calculate_video_size(self, max_width: float, max_height: float, 
                             video_path: Optional[Path] = None) -> Tuple[float, float]:
        """Calculate the appropriate size for a video within constraints."""
        from pptx.util import Inches
        
        # Get actual video dimensions if available
        if video_path:
            video_info = self.thumbnail_generator.get_video_info(str(video_path))
            if video_info and 'aspect_ratio' in video_info:
                aspect_ratio = video_info['aspect_ratio']
            else:
                # Fallback to 16:9 if we can't get video info
                aspect_ratio = 16 / 9
        else:
            # Default to 16:9 aspect ratio
            aspect_ratio = 16 / 9
        
        # Convert constraints from EMUs to inches
        max_width_inches = max_width / 914400
        max_height_inches = max_height / 914400
        
        # Calculate optimal size that fits within constraints
        constraint_aspect_ratio = max_width_inches / max_height_inches
        
        if aspect_ratio > constraint_aspect_ratio:
            # Video is wider than constraint area - fit by width
            video_width = Inches(max_width_inches)
            video_height = Inches(max_width_inches / aspect_ratio)
        else:
            # Video is taller than constraint area - fit by height
            video_height = Inches(max_height_inches)
            video_width = Inches(max_height_inches * aspect_ratio)
        
        return video_width, video_height
    
    def _get_video_mime_type(self, video_path: Path) -> str:
        """Get MIME type for video file."""
        extension = video_path.suffix.lower()
        mime_types = {
            '.mp4': 'video/mp4',
            '.avi': 'video/x-msvideo',
            '.mov': 'video/quicktime',
            '.wmv': 'video/x-ms-wmv',
            '.flv': 'video/x-flv',
            '.webm': 'video/webm',
            '.mkv': 'video/x-matroska',
            '.m4v': 'video/mp4'
        }
        return mime_types.get(extension, 'video/mp4')  # Default to mp4
    
    def _find_auto_poster_frame(self, video_path: Path) -> Optional[Path]:
        """Try to find a poster frame image with the same name as video."""
        video_stem = video_path.stem
        video_dir = video_path.parent
        
        image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
        
        for ext in image_extensions:
            poster_path = video_dir / f"{video_stem}{ext}"
            if poster_path.exists():
                return poster_path
            
            # Also try with _poster suffix
            poster_path = video_dir / f"{video_stem}_poster{ext}"
            if poster_path.exists():
                return poster_path
        
        return None
    
    def _extract_video_thumbnail(self, video_path: Path, alt_text: Optional[str] = None) -> Optional[Path]:
        """Extract thumbnail from video first frame."""
        try:
            thumbnail_path = self.thumbnail_generator.extract_video_thumbnail(str(video_path))
            if thumbnail_path and thumbnail_path.exists():
                return thumbnail_path
        except Exception as e:
            print(f"Warning: Could not extract thumbnail from video: {e}")
        
        # Fallback to placeholder if extraction fails
        return self._get_default_poster_frame(alt_text)
    
    def _get_default_poster_frame(self, alt_text: Optional[str] = None) -> Path:
        """Create or get path to default video poster frame."""
        # Create a simple default poster frame
        return self._create_video_placeholder(alt_text or "Video")
    
    def _create_video_placeholder(self, text: str = "Video") -> Path:
        """Create a simple placeholder image for video."""
        # Create a simple placeholder image
        from PIL import Image, ImageDraw, ImageFont
        
        # Create image
        width, height = 320, 180  # 16:9 aspect ratio
        img = Image.new('RGB', (width, height), color='#4472C4')  # Blue background
        
        # Add text
        draw = ImageDraw.Draw(img)
        
        try:
            # Try to use a font
            font = ImageFont.truetype("Arial", 24)
        except:
            # Fallback to default font
            font = ImageFont.load_default()
        
        # Calculate text position
        text_bbox = draw.textbbox((0, 0), text, font=font)
        text_width = text_bbox[2] - text_bbox[0]
        text_height = text_bbox[3] - text_bbox[1]
        
        x = (width - text_width) // 2
        y = (height - text_height) // 2
        
        draw.text((x, y), text, fill='white', font=font)
        
        # Add play button symbol
        play_size = 30
        play_x = width // 2
        play_y = height // 2 + 20
        
        # Draw triangle (play button)
        points = [
            (play_x - play_size//2, play_y - play_size//2),
            (play_x - play_size//2, play_y + play_size//2),
            (play_x + play_size//2, play_y)
        ]
        draw.polygon(points, fill='white')
        
        # Save to temp file
        import tempfile
        temp_dir = Path(tempfile.gettempdir())
        placeholder_path = temp_dir / f"video_placeholder_{hash(text) % 10000}.png"
        img.save(placeholder_path)
        
        return placeholder_path
    
    def validate_video(self, video_path: str) -> bool:
        """Validate that a video file exists and is readable."""
        try:
            resolved_path = self._resolve_media_path(video_path)
            return resolved_path is not None and resolved_path.exists()
        except Exception:
            return False
    
    def get_supported_formats(self) -> list:
        """Get list of supported video formats."""
        return ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.webm', '.mkv', '.m4v']
    
    def is_supported_format(self, video_path: str) -> bool:
        """Check if video format is supported."""
        path = Path(video_path)
        return path.suffix.lower() in self.get_supported_formats()